package vip.aster.system.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.CalendarUtil;
import cn.hutool.core.date.DatePattern;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.fastjson2.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import lombok.AllArgsConstructor;
import org.quartz.SchedulerException;
import org.springframework.stereotype.Service;
import vip.aster.common.constant.enums.StatusEnum;
import vip.aster.common.utils.PageInfo;
import vip.aster.quartz.constant.ScheduleConstants;
import vip.aster.quartz.service.ScheduleJobService;
import vip.aster.quartz.utils.CronUtils;
import vip.aster.quartz.vo.ScheduleJobVO;
import vip.aster.system.entity.SysNotice;
import vip.aster.system.mapper.SysNoticeMapper;
import vip.aster.system.query.SysNoticeQuery;
import vip.aster.system.service.SysNoticeService;
import vip.aster.system.vo.SysNoticeVO;
import vip.aster.websocket.constant.NoticeTypeEnum;
import vip.aster.websocket.utils.WebSocketUtils;
import vip.aster.websocket.vo.NoticeVO;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.util.List;

/**
 * <P>
 * 通知公告 服务实现类
 * </P>
 *
 * @author Aster lipian1004@163.com
 * @since 2024-03-12 11:47:01
 */
@Service
@AllArgsConstructor
public class SysNoticeServiceImpl extends ServiceImpl<SysNoticeMapper, SysNotice> implements SysNoticeService {
    private SysNoticeMapper sysNoticeMapper;
    private ScheduleJobService scheduleJobService;

    @Override
    public PageInfo<SysNoticeVO> pageList(SysNoticeQuery query) {
        Page<SysNotice> page = new Page<>(query.getPageNum(), query.getPageSize());
        Page<SysNotice> pageList = sysNoticeMapper.selectPage(page, getWrapper(query));
        return new PageInfo<>(SysNoticeVO.convertList(pageList.getRecords()), pageList.getTotal());
    }

    @Override
    public void save(SysNoticeVO vo) {
        SysNotice entity = vo.reconvert();

        if (StrUtil.isNotBlank(entity.getId())) {
            sysNoticeMapper.updateById(entity);
        } else {
            sysNoticeMapper.insert(entity);
        }
    }

    @Override
    public void publish(String id, String publishTime) throws SchedulerException {
        SysNotice notice = this.getById(id);

        // 发布内容
        NoticeVO notify = new NoticeVO(id, notice.getTitle(), notice.getNoticeType());
        String time = StrUtil.isBlank(publishTime) ? DateUtil.now() : publishTime;
        notify.setTime(time);
        String content = JSON.toJSONString(notify);

        // 发布时间为空则立即发布
        if (StrUtil.isBlank(publishTime)) {
            this.publishNotice(content);
        } else {
            // 定时发布
            ScheduleJobVO job = new ScheduleJobVO();
            job.setJobName(notice.getTitle());
            job.setJobGroup("notify");
            String invokeTarget = "sysNoticeServiceImpl.publishNotice(\"" + content + "\")";
            job.setInvokeTarget(invokeTarget);
            String cronExpression = CronUtils.generateCron(publishTime);
            job.setCronExpression(cronExpression);
            job.setMisfirePolicy(ScheduleConstants.MISFIRE_FIRE_AND_PROCEED);
            job.setConcurrent(StatusEnum.ENABLE.getValue());
            job.setStatus(ScheduleConstants.Status.NORMAL.getValue());
            scheduleJobService.save(job);
        }
    }

    @Override
    public void publishNotice(String content) {
        if (StrUtil.isNotBlank(content)) {
            WebSocketUtils.publishAll(content);
        }
    }

    @Override
    public SysNoticeVO getAnnouncement() {
        LambdaQueryWrapper<SysNotice> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(SysNotice::getNoticeType, NoticeTypeEnum.Announcement.getValue());
        queryWrapper.eq(SysNotice::getStatus, StatusEnum.ENABLE.getValue());

        String endTime = LocalDateTimeUtil.format(LocalDate.now().plusDays(1), DatePattern.NORM_DATE_PATTERN);

        String startTime = LocalDateTimeUtil.format(LocalDate.now().minusDays(3), DatePattern.NORM_DATE_PATTERN);

        queryWrapper.between(SysNotice::getCreateTime, DateUtil.parse(startTime), DateUtil.parse(endTime));
        queryWrapper.orderByDesc(SysNotice::getCreateTime);

        List<SysNotice> list = this.list(queryWrapper);
        if (CollUtil.isNotEmpty(list)) {
            return new SysNoticeVO(list.get(0));
        }
        return null;
    }

    private LambdaQueryWrapper<SysNotice> getWrapper(SysNoticeQuery query){
        LambdaQueryWrapper<SysNotice> wrapper = Wrappers.lambdaQuery();
        wrapper.like(StrUtil.isNotBlank(query.getTitle()), SysNotice::getTitle, query.getTitle());
        wrapper.eq(StrUtil.isNotBlank(query.getType()), SysNotice::getNoticeType, query.getType());
        wrapper.eq(StrUtil.isNotBlank(query.getStatus()), SysNotice::getStatus, query.getStatus());
        return wrapper;
    }

}